/**
* Project: yui3-common-hub
 * Class HubDataToDtoParser
 * Version 1.0
 * File Created at 2018年8月17日
 * $Id$
 * 
 * Copyright 2010-2015 Yui.com Corporation Limited.
 * All rights reserved.
 *
 * This software is the confidential and proprietary information of
 * Yui Personal. ("Confidential Information").  You shall not
 * disclose such Confidential Information and shall use it only in
 * accordance with the terms of the license agreement you entered into
 * with Yui.com.
 */
package yui.comn.hub.data.parser;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.LinkedHashMap;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.CollectionUtils;

import yui.comn.hub.data.handler.HubDataHandlerProcess;
import yui.comn.hub.model.HubXmlColumn;
import yui.comn.hub.model.Symbol;
import yui.comn.hub.utils.HubDataToDtoUtils;
import yui.comn.hub.utils.HubStringUtils;

/**
 * 把map对象解析成dto对象
 * @author yuyi (1060771195@qq.com)
 */
public class HubDataToDtoParser {
    private Logger logger = LoggerFactory.getLogger(HubDataToDtoParser.class);
    
    private static HubDataToDtoParser parser = new HubDataToDtoParser();
     
    public static HubDataToDtoParser getInstance() {
        return parser;
    }
    
    /**
     * 通过反射机制，实例化对象，并且给对象属性赋值
     */
    public void toObjSetVal(Object obj, HubXmlColumn col, Object val) {
//        if (StringUtils.isNotBlank(col.getEnCls())
//                && !StringUtils.equals(col.getEnCls(), Clazz.class.getName())) {
//            val = EnumUtils.getCd(col.getEnumClass(), String.valueOf(val));
//        }
        String mapper = col.getMapper();
        String[] attrs = StringUtils.split(mapper, Symbol.DOT);
        try {
            //实例化对象中的对象
            Object defObj = obj;
            for (int i = 0; i < attrs.length - 1; i++) {
                defObj = toDefObjByAttr(defObj, attrs[i]);
            }
            
            //给对象属性赋值
            Field field = defObj.getClass().getDeclaredField(attrs[attrs.length - 1]);
            String methodName = HubStringUtils.getSetMethodName(field.getName());
            Method method = defObj.getClass().getMethod(methodName, field.getType());
            
            if (!CollectionUtils.isEmpty(col.getHandlerConfigs())) {
            	Map<String, Object> resultMap = new LinkedHashMap<>();
            	resultMap.put(col.getName(), val);
            	HubDataHandlerProcess.getInstance().handle(col, resultMap);
            	val = resultMap.get(col.getName());
            }
            
            Object distTypeVal = HubDataToDtoUtils.toDistTypeVal(field.getType(), val);
            
            method.invoke(defObj, distTypeVal);
            
        } catch (Exception e) {
            String errMsg = "实例化对象，并且给对象属性赋值, mapper=" + mapper;
            logger.error(errMsg, e);
            throw new RuntimeException(errMsg, e);
        }
    }
    
    /**
     * 通过反射机制，通过属性名称，实例化对象中的对象(该对象不是基本类型，一般是自定义对象)
     */
    public Object toDefObjByAttr(Object pObj, String attrName) {
        try {
            Class<?> clazz = pObj.getClass();
            Method getMethod = clazz.getMethod(HubStringUtils.getGetMethodName(attrName));
            Object obj = getMethod.invoke(pObj);
            
            //对象中的对象，通过反射机制获取对象，如果该对象是null，实例化属性对象
            if (null == obj) {
                obj = getMethod.getReturnType().newInstance();
                Method setMethod = clazz.getMethod(HubStringUtils.getSetMethodName(attrName), getMethod.getReturnType());
                setMethod.invoke(pObj, obj); 
            }
            
            return obj;
        } catch (Exception e) {
            String errMsg = "获取方法值失败, attrName=" + attrName;
            logger.error(errMsg, e);
            throw new RuntimeException(errMsg, e);
        }
    }
    
    /**
     * 通过类反射，实例化对象
     */
    public Object toObjByClass(Class<?> clazz) {
        try {
            return clazz.newInstance();
        } catch (Exception e) {
            return null;
        } 
    }
}
